#include "Thread.hpp"
#include <pthread.h>
#include <string>

using namespace std;


string GetThreadname()
{
    static int num = 1;
    char name[64];
    snprintf(name, sizeof(name), "thread_%d", num++);
    return (string)name;
}

void Print()
{
    while(1)
    {
        cout << "hello, hello, hello: " << endl;
        sleep(1);
    }
}

int ticket = 10000;
pthread_mutex_t mutex;
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 全局的锁，定义并初始化了

void *route(void *arg)
{
    char *id = (char*)arg;
    while ( 1 ) 
    {
        pthread_mutex_lock(&mutex);
        if ( ticket > 0 ) 
        {
            usleep(1000);
            printf("%s sells ticket:%d\n", id, ticket);
            ticket--;
            pthread_mutex_unlock(&mutex);
        }       
        else  
        {
            pthread_mutex_unlock(&mutex);
            break;
        }
    }
} 
int main( void )
{
    pthread_t t1, t2, t3, t4;
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&t1, NULL, route, (void *)"thread 1");
    pthread_create(&t2, NULL, route, (void *)"thread 2");
    pthread_create(&t3, NULL, route, (void *)"thread 3");
    pthread_create(&t4, NULL, route, (void *)"thread 4");

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);
    pthread_mutex_destroy(&mutex);
    return 0;
}

// 加锁：
// 1. 尽可能给少的代码块加锁
// 2. 一般加锁都是给临界区加锁
// void GetTicket(string name)
// {
//     while(true)
//     {
//         pthread_mutex_lock(&mutex);
//         if(ticket > 0)
//         {
//             // 模拟抢票时间
//             usleep(1000);
//             printf("%s get a ticket: %d\n", name.c_str(), ticket);
//             ticket--;
//             pthread_mutex_unlock(&mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(&mutex);
//             break;
//         }
//     }
// }

// int main()
// {
//     string name1 = GetThreadname();
//     Thread<string> t1(GetTicket, name1, name1);

//     string name2 = GetThreadname();
//     Thread<string> t2(GetTicket, name2, name2);

//     string name3 = GetThreadname();
//     Thread<string> t3(GetTicket, name3, name3);

//     string name4 = GetThreadname();
//     Thread<string> t4(GetTicket, name4, name4);

//     t1.Start();
//     t2.Start();
//     t3.Start();
//     t4.Start();

//     t1.Join();
//     t2.Join();
//     t3.Join();
//     t4.Join();

//     return 0;
// }

// int main()
// {
//     const int num = 5;
//     vector<Thread> Threads;

//     for(int i = 0; i < num; i++)
//     {
//         Thread t(Print, GetThreadname());
//         Threads.push_back(t);
//     }

//     for(auto &t : Threads)
//     {
//         cout << t.threadname() << " is running: " << t.IsRunning() << endl;
//     }

//     for(auto &t : Threads)
//     {
//         t.Start();
//     }

//     for(auto &t : Threads)
//     {
//         cout << t.threadname() << " is running: " << t.IsRunning() << endl;
//     }

//     for(auto &t : Threads)
//     {
//         t.Join();
//     }
//     return 0;
// }

// 测试
// int main()
// {
//     Thread<int> t(Print, GetThreadname(), 10);
    
//     t.Start();

//     t.Join();

//     return 0;
// }